﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.MathLib.CSG
{
   class Block<T>
    {
        public T datum;
        public Block<T> next;
        public Block<T> prev;
    }
   class IterPool<T> where T : new()
    {
        int index;
        Block<T> block_list;
        List<Block<T>> pool;
        public IterPool()
        {
            this.pool = new List<Block<T>>();
        }
        public IterPool(IterPool<T> src) : this()
        {
            this.MoveFrom(src);
        }
        void clear()
        {
            block_list = null;
            pool.Clear();
        }

        public void MoveFrom(IterPool<T> src)
        {
            this.clear();
            block_list = src.block_list;
            pool.AddRange(src.pool);
            src.clear();
        }

        /// <summary>
        /// 向链的头部加入新元素
        /// </summary>
        /// <returns></returns>
        public Block<T> alloc()
        {
            Block<T> new_block = new Block<T>();
            new_block.datum = new T();
            if (new_block.datum is IIndex)
            {
                (new_block.datum as IIndex).i = index++;
            }
         
            if (block_list != null) block_list.prev = new_block;
            new_block.next = block_list;
            new_block.prev = null;
            block_list = new_block;
            pool.Add(new_block);
            return new_block;
        }
        public void free(Block<T> item)
        {
            if (item == null) return;
            if (item.next != null) item.next.prev = item.prev;
            if (item.prev != null) item.prev.next = item.next;
            if (item == block_list) block_list = item.next;
            pool.Remove(item);
        }
        public void free(T ditem)
        {
            var item = pool.FirstOrDefault((it) => Object.Equals(it.datum, ditem));
            free(item);
        }
        public Block<T> find(T ditem)
        {
            return pool.FirstOrDefault((it) => Object.Equals(it.datum, ditem));
        }
        public Block<T> getFirst() { return block_list; }
        public Block<T> getNext(Block<T> prev) { return prev.next; }

        public void for_each(Action<T> func)
        {
            for (Block<T> block = block_list; block != null; block = block.next)
            {
                func(block.datum);
            }
        }
        public bool contains(Block<T> tptr)
        {
            for (Block<T> block = block_list; block != null; block = block.next)
            {
                if (tptr == block)
                    return true;
            }
            return false;
        }
        int size()
        {
            return this.pool.Count;
        }
    }

}
